﻿using gixoom.ClientShell.Properties;
using gixoom.Dom;
using gixoom.Dom.Block;
using gixoom.Dom.Score;
using gixoom.Dom.Storage.File;
using Ninject;
using Ninject.Modules;
using System.IO;

namespace gixoom.ClientShell
{
    internal class ClientShellModule: NinjectModule
    {
        private string personalDirectoryPath;
        private string[] addresses;
        
        /// <summary>
        /// Creates ClientShellModule object.
        /// </summary>
        /// <param name="personalDirectoryPath">the path of the personal directory</param>
        /// <param name="addresses">host addresses</param>
        /// <exception cref="System.ArgumentNullException">One of the arguments is a null reference.</exception>
        /// <exception cref="System.ArgumentException"><i>personalDirectoryPath</i> is an empty string or
        /// <i>addresses</i> length is 0.</exception>
        public ClientShellModule(string personalDirectoryPath, string[] addresses)
        {
            Ensure.ArgumentNotNull(personalDirectoryPath, "personalDirectoryPath");
            Ensure.StringArgumentNotEmpty(personalDirectoryPath, "personalDirectoryPath");
            Ensure.ArgumentNotNull(addresses, "addresses");
            Ensure.EnoughItems(addresses, 1, "addresses");

            this.personalDirectoryPath = personalDirectoryPath;
            this.addresses = addresses;
        }

        public override void Load()
        {
            Bind<IKernel>().ToConstant(Kernel);

            var domFacade = CreategixoomDomFacade(addresses);
            BindScoreFacade(domFacade);
            BindBlockFacade(domFacade);
            BindFileStorage(domFacade);
        }

        private IgixoomDomFacade CreategixoomDomFacade(string[] addresses)
        {
            var domModule = new gixoomDomModule(addresses);
            var domKernel = new StandardKernel(domModule);
            var domFacade = new gixoomDomFacade(domKernel);

            return domFacade;
        }

        private void BindScoreFacade(IgixoomDomFacade domFacade)
        {
            var scoreFacade = domFacade.GetScoreFacade();
            Bind<IScoreFacade>().ToConstant(scoreFacade);
        }

        private void BindBlockFacade(IgixoomDomFacade domFacade)
        {
            var blockFacade = domFacade.GetBlockFacade();
            Bind<IBlockFacade>().ToConstant(blockFacade);
        }

        private void BindFileStorage(IgixoomDomFacade domFacade)
        {
            var fileStorageFacade = domFacade.GetFileStorageFacade();
            string pathForExtractedFiles = EnsureSlashInTheEnd(personalDirectoryPath) +
                Resources.nameExtractedFilesFolder;

            if (!Directory.Exists(pathForExtractedFiles))
            {
                // TODO: null case should be processed
                var directoryInfo = CreateDirectory(pathForExtractedFiles);
            }

            var fileStorage = fileStorageFacade.CreateFileStorage(pathForExtractedFiles);
            Bind<IFileStorage>().ToConstant(fileStorage);
        }

        private DirectoryInfo CreateDirectory(string path)
        {
            DirectoryInfo directoryInfo = null;

            // TODO: all exceptions should be properly processed
            try
            {
                directoryInfo = Directory.CreateDirectory(path);
            }
            catch
            {
            }

            return directoryInfo;
        }

        private string EnsureSlashInTheEnd(string s)
        {
            string result = (s[s.Length - 1] == '\\') ?
                s : s + '\\';

            return result;
        }
    }
}
